#pragma once

#include "Locker.h"
#include <string>
#include <WinSock2.h>

namespace TCP
{

class Client;
class Server;
class Accept;

class Init
{
public:
	Init();

	~Init();

public:
	bool init();

	void uninit();

private:
	bool	_isInit;
};

class ClientObserver
{
public:
	virtual void onRecv(Client *rv, const void *data, int dataLen){}
};

class Client
{
public:
	Client(void);

	~Client(void);

public:
	bool start(const std::string &serverIP, int serverPort, ClientObserver *co);

	void stop();

	bool isStart();

	ClientObserver *observer();

	std::string serverIP();

	int serverPort();

public:
	int recv(char *buf, int len);

	int send(char *buf, int len);

private:
	bool real_start();

	void real_stop();

	bool real_isStart();

private:
	std::string		_serverIP;
	int				_serverPort;
	ClientObserver	*_observer;

private:
	SOCKET	_socket;

private:
	static DWORD CALLBACK threadFun(VOID *param);

private:
	BOOL	_threadRun;
	HANDLE	_thread;
};

class AcceptObserver
{
public:
	virtual void onSock(Accept *at, SOCKET sock){}
};

class Accept
{
public:
	Accept(void);

	~Accept(void);

public:
	bool start(const std::string &listenIP, int listenPort, AcceptObserver *so);

	void stop();

	bool isStart();

	AcceptObserver *observer();

	std::string listenIP();

	int listenPort();

public:
	int recv(char *buf, int len);

	int send(char *buf, int len);

private:
	std::string		_listenIP;
	int				_listenPort;
	AcceptObserver	*_observer;

private:
	SOCKET	_socket;

private:
	static DWORD CALLBACK threadFun(VOID *param);

private:
	bool real_start();

	void real_stop();

	bool real_isStart();

private:
	BOOL	_threadRun;
	HANDLE	_thread;
	bool	_realStart;
};


class ServerObserver
{
public:
	virtual void onRecv(Server *sr, const void *data, int dataLen){}

	virtual void onClose(Server *sr){}
};

class Server
{
public:
	Server(void);

	~Server(void);

public:
	bool start(SOCKET sock, ServerObserver *so);

	void stop();

	bool isStart();

	ServerObserver *observer();

	std::string clientIP();

	int clientPort();

	std::string localIP();

	int localPort();

public:
	int recv(char *buf, int len);

	int send(char *buf, int len);

private:
	void getip(int (CALLBACK *fun)(SOCKET s, sockaddr *addr, int *addrLen), std::string &ip, int &port);

private:
	ServerObserver	*_observer;

private:
	SOCKET	_socket;

private:
	static DWORD CALLBACK threadFun(VOID *param);

private:
	BOOL	_threadRun;
	HANDLE	_thread;
};
}